package com.box2dwrapper.manager
{
	import Box2D.Collision.Shapes.b2Shape;
	import Box2D.Collision.b2AABB;
	import Box2D.Common.Math.b2Vec2;
	import Box2D.Dynamics.Joints.b2MouseJoint;
	import Box2D.Dynamics.Joints.b2MouseJointDef;
	import Box2D.Dynamics.b2Body;
	import Box2D.Dynamics.b2World;
	
	import com.box2dwrapper.view.core.AbstractView;
	
	import flash.events.MouseEvent;
	
	public class DragManager
	{
		public static var stage:*;
		public static var mousePVec:b2Vec2;
		public static var world:b2World;		
		public static var mouseJoint:b2MouseJoint;
				
		public static var mouseXWorldPhys:Number;
		public static var mouseYWorldPhys:Number;
		public static var mouseXWorld:Number;
		public static var mouseYWorld:Number;
		
		public static var allowDrag:Boolean = false;
				
		public static function initialize(_stage:*, _world:b2World):void
		{
			stage = _stage;
			world = _world;
			mousePVec = new b2Vec2();
			allowDrag = true;
		}
		
		public static function clear():void
		{
			allowDrag = false;
		}
		
		public static function updateMouseWorld():void
		{
			mouseXWorldPhys = (Input.mouseX) / AbstractView.SCALE; 
			mouseYWorldPhys = (Input.mouseY) / AbstractView.SCALE; 
			mouseXWorld = (Input.mouseX); 
			mouseYWorld = (Input.mouseY);
		}
		
		public static function mouseDrag():void
		{
			if(Input.mouseDown && !mouseJoint){
				
				var body:b2Body = getBodyAtMouse();
				
				if(body)
				{
					var md:b2MouseJointDef = new b2MouseJointDef();
					md.body1 = world.GetGroundBody();
					md.body2 = body;
					md.target.Set(mouseXWorldPhys, mouseYWorldPhys);
					md.maxForce = 300.0 * body.GetMass();
					md.timeStep = AbstractView.TIME_STEP;
					mouseJoint = world.CreateJoint(md) as b2MouseJoint;
					body.WakeUp();
				} 
			}
			
			if(!Input.mouseDown){
				if (mouseJoint)
				{
					world.DestroyJoint(mouseJoint);
					mouseJoint = null;
				}
			}
			
			if (mouseJoint && allowDrag)
			{
				var p2:b2Vec2 = new b2Vec2(mouseXWorldPhys, mouseYWorldPhys);
				mouseJoint.SetTarget(p2);
			}
		}
		
		public static function mouseDestroy():void
		{
			// mouse press
			if (!Input.mouseDown)
			{
				var body:b2Body = getBodyAtMouse(true);
				
				if(body)
				{
					world.DestroyBody(body);
					return;
				}
			}
		}
		
		public static function getBodyAtMouse(includeStatic:Boolean = false):b2Body
		{
			mousePVec.Set(mouseXWorldPhys, mouseYWorldPhys);
			var aabb:b2AABB = new b2AABB();
			aabb.lowerBound.Set(mouseXWorldPhys - 0.001, mouseYWorldPhys - 0.001);
			aabb.upperBound.Set(mouseXWorldPhys + 0.001, mouseYWorldPhys + 0.001);
			
			var maxCount:int = 10;
			var shapes:Array = new Array();
			var count:int = world.Query(aabb, shapes, maxCount);
			var body:b2Body = null;
			
			for (var i:int = 0; i < count; ++i)
			{
				if (shapes[i].GetBody().IsStatic() == false || includeStatic)
				{
					var tShape:b2Shape = shapes[i] as b2Shape;
					var inside:Boolean = tShape.TestPoint(tShape.GetBody().GetXForm(), mousePVec);
					if (inside)
					{
						body = tShape.GetBody();
						break;
					}
				}
			}
			return body;
		}

	}
}